/*
 * cel bitmap interface implemented source file 
 * @author chenxin <chenxin619315@gmail.com>
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h> //CHAR_BIT
#include "bitmaplib.h"

#ifdef DEBUG
	#define debug_print printf
#else
	#define debug_print
#endif

static int cel_bitmap_init(cel_bitmap_t *map, int opacity);
static int cel_bitmap_destroy(cel_bitmap_t *map);

/* create a new bitmap with a specified opacity */
cel_bitmap_t *new_cel_bitmap(int opacity)
{
	cel_bitmap_t *map = (cel_bitmap_t *)malloc(sizeof(cel_bitmap_t));
	if(map == NULL) {
		perror("new_cel_bitmap malloc");
		return NULL;
	}

	if(cel_bitmap_init(map, opacity) < 0)
	{
		free(map);
	}

	return map;
}

static int cel_bitmap_init(cel_bitmap_t *map, int opacity)
{
	unsigned int bytes = (opacity + CHAR_BIT - 1) / CHAR_BIT;
	map->bit = (char *)calloc(bytes, sizeof(char));

	if(map->bit == NULL) {
		perror("cel_bitmap_init calloc");
		return -1;
	}

	map->length = bytes * CHAR_BIT;
	map->size = 0;

	memeset(map->bit, 0x00, bytes);

	return 0;
}

/* free the specified cel_bitmap_t */
void free_cel_bitmap(cel_bitmap_t **map)
{
	if(map == NULL)
		return;

	if(*map != NULL)
	{
		cel_bitmap_destroy(*map);
		free(*map);
		*map = NULL;
	}
}

static int cel_bitmap_destroy(cel_bitmap_t *map)
{
	if(map != NULL)
	{
		free(map->bit);
		map->bit = NULL;
	}
	return 0;
}

/* set the specified bit to 1 */
void cel_bitmap_set(cel_bitmap_t *map, unsigned int idx)
{
	if(map != NULL && idx < map->length)
	{
		map->bit[idx/CHAR_BIT] |= (0x01 << (idx % CHAR_BIT));
		map->size++;
	}
}

/* set the specified bit to 0 */
void cel_bitmap_remove(cel_bitmap_t *map, unsigned int idx)
{
	if(map != NULL && idx < map->length)
	{
		map->bit[idx/CHAR_BIT] &= (~(0x01 << (idx % CHAR_BIT)));
		map->size++;
	}
}

/* get the specified bit */
int cel_bitmap_get(cel_bitmap_t *map, unsigned int idx)
{
	if(map == NULL)
		return 0;
	if(idx >= map->length)
		return 0;

	if((map->bit[idx/CHAR_BIT] & (0x01 << (idx % CHAR_BIT))) != 0)
		return 1;
	return 0;
}




